/*
board-games:	An educational framework for board games programming.
    Copyright (C) 2008  Daniel Gutson, FuDePAN
    
    This file is part of board-games.

    board-games is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    board-games is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
*/

#ifndef PLAYERS_SIDE
#define PLAYERS_SIDE

#include "player_sdk/player.h"

class PlayerData
{
    pid_t pid;
    //MQueue mqueue_to_player;
    //MQueue mqueue_from_player;
    Pipe pipe_to_player;
    Pipe pipe_from_player;
        
public:
    
    void load(const char* objname);

    void send_message(const void* msgdata, size_t size)
    {
        //mqueue_to_player.send_message(msgdata, size);
        //mqueue_from_player.receive_message(response, response_size);
            
        pipe_to_player.send_message(msgdata, size);
    }

    void receive_message(void*& response, size_t& response_size)
    {
        //mqueue_to_player.send_message(msgdata, size);
        //mqueue_from_player.receive_message(response, response_size);
            
        pipe_from_player.receive_message(response, response_size);
    }

    static void abort_current_connection()
    {
        Pipe::abort_current_connection();
    }
    
    //pid_t get_pid() const { return pid; }
    bool is_running() const
    {
        //int status;
        return waitpid(pid, NULL /* &status */, WNOHANG) == 0;
    }

    void kill()
    {
        ::kill(pid, SIGKILL);
    }
    
    void set_player_timeout(size_t milliseconds)
    {
        pipe_from_player.set_timeout(milliseconds);
        pipe_to_player.set_timeout(milliseconds);
    }
    
    void disable_timeout()
    {
        pipe_from_player.disable_timeout();
        pipe_to_player.disable_timeout();
    }
};

//int RxAlgorithm::current_abort_fd = RxAlgorithm::NO_FD;


class PlayerProcess : private PlayerAPI
{
    ShObj shobj;
    //MQueue mqueue_from_referee;
    //MQueue mqueue_to_referee;
    RxPipeHandler pipe_from_referee;
    TxPipeHandler pipe_to_referee;
    
    const size_t random_seed;

    Player* player;

    PlayerProcess(const char* objname, const RxPipeHandler& from_referee, const TxPipeHandler& to_referee, size_t rand_seed);

    ~PlayerProcess()
    {
        pipe_from_referee.close_fd();
        pipe_to_referee.close_fd();

        delete player;        
    }
    
    virtual void send_message_to_referee(const void* msgdata, size_t size)
    {
        pipe_to_referee.send_message(msgdata, size);
    }
    
    virtual void receive_message_from_referee(void*& msgdata, size_t& size)
    {
        pipe_from_referee.receive_message(msgdata, size);
    }
    
    virtual size_t get_srand() const
    {
        return random_seed;
    }
    
    virtual void connect_board_with_referee(SharedBoard& board)
    {
        int shmid;
        PlayerAPI::receive_message_from_referee(shmid);
        board.share_connect(shmid);
    }

    //void process_loop();
public:
    static void run(const char* objname, const RxPipeHandler& from_referee, const TxPipeHandler& to_referee, size_t random_seed);
};

extern void player_sig_segv_handler(int sig);

#endif
